package com.amphora.util.repository;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class JPAUtil {

	public static String PU_NAME = "Amphora-BETA";
	
	public static EntityManagerFactory theEntityManagerFactory = null;  
	
	public static final ThreadLocal<EntityManager> ENTITY_MANAGERS = new ThreadLocal<EntityManager>();
	
	public static void init(){
		theEntityManagerFactory = Persistence.createEntityManagerFactory(PU_NAME);
	}
	
    public static void setEntityManager()  
    {  
    	ENTITY_MANAGERS.set(theEntityManagerFactory.createEntityManager());
    }
    
    public static EntityManager getEntityManager()  
    {  
        return ENTITY_MANAGERS.get();  
    }
    
    public static void close(){
    	theEntityManagerFactory.close();
	}
    
    public static void removeInstance(){
		EntityManager em = getEntityManager();
		ENTITY_MANAGERS.remove();
		try{
			 if(em != null)
	             em.close();
        }catch(Throwable t){
        	System.out.println("While closing an EntityManager"+t.toString());
        }  
	}
    
    // 	--- Persistence Unit Convenience Query Methods ---
    
    public static <T>T findById(Class<T> entityClass, Long id){
		try{
			return getEntityManager().find(entityClass, id);
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}
    
    public static <T>List<T> findByType(Class<T> entityClass){
		return findByQuery("from " + entityClass.getSimpleName());
	}
    
    public static <T>List<T> findByIds(Class<T> entityClass, List<Long> ids){
		return findByIdsAll(entityClass, "id", ids);
	}
	
	@SuppressWarnings("unchecked")
	public static <T>List<T> findByIdsAll(Class<T> entityClass, String identifierField, List<Long> ids){
		try{
			Query q = createQuery("from " + entityClass.getSimpleName() + " where " + identifierField + " in (:ids)");
			q.setParameter("ids", ids);
			return (List<T>)q.getResultList();
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}
	@SuppressWarnings("unchecked")
	public static <T>T findSingleItemByQuery(Class<T> entityClass,String query){
		try{
			return (T)createQuery(query).getSingleResult();
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public static <T>List<T> findByQuery(String query){
		try{
			return (List<T>)createQuery(query).getResultList();
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}

	public static Query createQuery(String q){
		return getEntityManager().createQuery(q);
	}
	
	public static void createEntity(Object obj){
		EntityManager em = getEntityManager();
		EntityTransaction trans = em.getTransaction();
		trans.begin();
		em.persist(obj);
		trans.commit();
	}
	
	public static void delete(Object obj){
		EntityManager em = getEntityManager();
		EntityTransaction trans = em.getTransaction();
		trans.begin();
		em.remove(obj);
		trans.commit();
	}
	
	public static <T> void update(Class<T> entity,Long id){
		EntityManager em = getEntityManager();
		EntityTransaction trans = em.getTransaction();
		trans.begin();
		Object o = findById(entity, id);
		em.merge(o);
		trans.commit();
	}
}
